#include "Buffer.h"


#include <unistd.h>
#include <sys/uio.h>
#include <cerrno>

// 从fd上读数据
// Buffer缓冲区是有大小的，但是从fd上读数据的时候，可能不知道tcp数据最终的大小
ssize_t Buffer::readFd(int fd, int *saveError)
{
    char extrabuf[65536] = {0}; // 栈上的内存空间 64k
                                // 当m_buffer暂时不够用时暂存数据，待buffer重写分配空间后，再把数据交给m_buffer
    struct iovec vec[2]; // vec有两个缓冲区

    const size_t writable = writableBytes(); // Buffer底层缓冲区剩余的可读写空间大小
    vec[0].iov_base = begin() + m_writerIndex;
    vec[0].iov_len = writable;

    vec[1].iov_base = extrabuf;
    vec[1].iov_len = sizeof(extrabuf);

    // 如果Buffer可写缓冲区小于extrabuf(64k)，则Buffer和extrabuf(64k)都会被使用
    // 如果Buffer可写缓冲区大于或等于extrabuf(64k)，则只使用Buffer
    const int iovcnt = ( writable < sizeof(extrabuf) ) ? 2 : 1;
    // Buffer缓冲区存不下，则将数据暂时存入extrabuf(64k)中
    const ssize_t n = ::readv(fd, vec, iovcnt);
    if (n < 0) {
        *saveError = errno;
    } else if (n <= writable) {
        // Buffer的可写缓冲区已经能够存储从fd读取出来的数据
        m_writerIndex += n;
    } else {
        // extrabuf里面页写入了数据
        m_writerIndex = m_buffer.size();
        append(extrabuf, n - writable); // 从m_writerIndex开始写 n - writable大小的数据
    }

    return n;
}

// 通过fd发送数据
ssize_t Buffer::writeFd(int fd, int *saveError)
{
    ssize_t n = ::write(fd, peek(), readableBytes());
    if (n < 0) {
        *saveError = errno;
    }
    return n;
}
